package icu.d4peng.cloud.user.service.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wf.captcha.base.Captcha;
import icu.d4peng.cloud.common.cache.service.CacheService;
import icu.d4peng.cloud.common.captcha.exception.CaptchaException;
import icu.d4peng.cloud.common.captcha.service.CaptchaService;
import icu.d4peng.cloud.common.core.util.OrikaFactory;
import icu.d4peng.cloud.common.core.vo.ListVO;
import icu.d4peng.cloud.common.core.vo.ResultVO;
import icu.d4peng.cloud.user.constant.UserConstant;
import icu.d4peng.cloud.user.dao.UserDao;
import icu.d4peng.cloud.user.entity.User;
import icu.d4peng.cloud.user.enums.Status;
import icu.d4peng.cloud.user.exception.UserException;
import icu.d4peng.cloud.user.request.*;
import icu.d4peng.cloud.user.service.UserService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author d4peng
 * @version 1.0.0
 * @date 2021-12-30 21:08
 * @description UserServiceImpl:用户服务类
 */
@Service
public class UserServiceImpl implements UserService {
    private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);
    private final UserDao userDao;
    private final CaptchaService captchaService;
    private final CacheService cacheService;

    @Autowired
    public UserServiceImpl(UserDao userDao, CaptchaService captchaService, CacheService cacheService) {
        this.userDao = userDao;
        this.captchaService = captchaService;
        this.cacheService = cacheService;
    }

    @Override
    public ResultVO<String> captcha(CaptchaRequest captchaRequest) {
        // 1.获得缓存的key
        String cacheId = captchaRequest.getUsername();

        // 2.获得验证码的值
        Captcha captcha = this.captchaService.getCaptcha();
        LOGGER.info("captcha text is:{}", captcha.text());

        this.cacheService.getCacheChannel().set(UserConstant.CAPTCHA.value(), cacheId, captcha.text(), false);

        // 3.返回验证的base64
        return ResultVO.<String>success(captcha.toBase64());
    }

    @Override
    public ResultVO<String> register(RegisterRequest registerRequest) {
        validateCode(registerRequest.getUsername(), registerRequest.getCode());

        QueryWrapper<User> queryWrapper = new QueryWrapper<User>().eq("username", registerRequest.getUsername());
        List<User> users = this.userDao.selectList(queryWrapper);
        if (users != null && users.size() > 0) {
            LOGGER.error("用户已存在,请检查!");
            throw new UserException("用户已存在,请检查!");
        }

        User user = OrikaFactory.map(registerRequest, User.class).setStatus(Status.NORMAL);
        int result = this.userDao.insert(user);

        return result == 0 ? ResultVO.<String>fail("失败!") : ResultVO.<String>success("成功!");
    }

    @Override
    public ResultVO<SaTokenInfo> login(LoginRequest loginRequest) {
        // 1. 验证验证码
        validateCode(loginRequest.getUsername(), loginRequest.getCode());

        // 2. 验证用户是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>().eq("username", loginRequest.getUsername());
        User user = this.userDao.selectOne(queryWrapper);
        if (user == null) {
            LOGGER.info("用户不存在,请检查!");
            throw new UserException("用户不存在,请检查!");
        }

        // 3. 验证密码是否正确
        if (!user.getPassword().equals(loginRequest.getPassword())) {
            LOGGER.info("密码不正确,请检查!");
            throw new UserException("密码不正确,请检查!");
        }

        // 4. 生成Token
        StpUtil.login(user.getId());
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();

        // 5.返回结果
        return ResultVO.<SaTokenInfo>success(tokenInfo);
    }

    @Override
    public ResultVO<String> info(Long id) {
        return ResultVO.<String>success(StpUtil.getTokenValueByLoginId(id));
    }

    @Override
    public ResultVO<String> logout(Long id) {
        StpUtil.logout(id);
        return ResultVO.<String>success("登出成功!");
    }

    @Override
    public ListVO<User> list(ListRequest listRequest) {
        // 1. 构造查询条件
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
        if (ObjectUtils.isNotEmpty(listRequest.getId())) {
            queryWrapper = queryWrapper.eq("id", listRequest.getId());
        }
        if (StringUtils.isNotEmpty(listRequest.getUsername())) {
            queryWrapper = queryWrapper.like("username", listRequest.getUsername());
        }
        if (StringUtils.isNotEmpty(listRequest.getNickName())) {
            queryWrapper = queryWrapper.like("nick_name", listRequest.getNickName());
        }
        if (StringUtils.isNotEmpty(listRequest.getPhone())) {
            queryWrapper = queryWrapper.eq("phone", listRequest.getPhone());
        }

        // 2. 查询
        Page<User> page = this.userDao.selectPage(listRequest, queryWrapper);
        return ListVO.<User>success(page.getRecords());
    }

    @Override
    public ResultVO<User> get(Long id) {
        return ResultVO.<User>success(this.userDao.selectById(id).setPassword(""));
    }

    @Override
    public ResultVO<String> delete(Long id) {
        int result = this.userDao.deleteById(id);
        return result == 0 ? ResultVO.<String>fail("失败!") : ResultVO.<String>success("成功!");
    }

    @Override
    public ResultVO<String> modify(ModifyRequest modifyRequest) {
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<User>().set("id", modifyRequest.getId());
        if (StringUtils.isNotEmpty(modifyRequest.getPhone())) {
            updateWrapper = updateWrapper.set("phone", modifyRequest.getPhone());
        }
        if (StringUtils.isNotEmpty(modifyRequest.getPassword())) {
            updateWrapper = updateWrapper.set("password", modifyRequest.getPassword());
        }
        if (StringUtils.isNotEmpty(modifyRequest.getNickName())) {
            updateWrapper = updateWrapper.set("nick_name", modifyRequest.getNickName());
        }
        if (StringUtils.isNotEmpty(modifyRequest.getEmail())) {
            updateWrapper = updateWrapper.set("email", modifyRequest.getEmail());
        }
        if (StringUtils.isNotEmpty(modifyRequest.getAvatar())) {
            updateWrapper = updateWrapper.set("avatar", modifyRequest.getAvatar());
        }
        if (StringUtils.isNotEmpty(modifyRequest.getRemark())) {
            updateWrapper = updateWrapper.set("remark", modifyRequest.getRemark());
        }
        int result = this.userDao.update(null, updateWrapper);
        return result == 0 ? ResultVO.<String>fail("失败!") : ResultVO.<String>success("成功!");
    }

    /**
     * 校验验证码
     *
     * @param username 用户名
     * @param code     验证码
     */
    private void validateCode(String username, String code) {
        String captcha = this.cacheService.getCacheChannel().get(UserConstant.CAPTCHA.value(), username, false).asString();
        if (captcha.equalsIgnoreCase("null") || !captcha.equalsIgnoreCase(code)) {
            LOGGER.info("验证码不正确!");
            throw new CaptchaException("验证码不正确!");
        }
        this.cacheService.getCacheChannel().evict(UserConstant.CAPTCHA.value(), username);
    }
}
